package martin.tpfinal.reconocer.procesar.separateCoef;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;


/**
 * Ingresa un nombre de archivo y el numero de numeros que tiene cada file de este.
 * Al ejecutar queda una matriz de numeros flotantes, con la misma estructura que el archivo 
 * de enntrada, pero los valores de esta matriz estan normalizados.
 * 
 * @author Martin
 *
 */
public class FromFileToDoubleArray {
	
	private static final Logger  logger  = Logger.getLogger(FromFileToDoubleArray.class);

	public static Double maximo=new Double(0.0);
	public static Double minimo=new Double(0.0);

	//Voy a poner como limite de normalizacion de valores a 
	//max -> 146; min -> -100; paso a positivos sumandoles 100 a todos
	//(los que queden negativos los paso al minimo 0, lo mismo los que se pasan para arriba 246)
	public static Double maxNorm=new Double(246.0);
	public static Double minNorm=new Double(0.0);
	public static Double deltaNorm=new Double(100.0);
	
	private List< List<Double> > matriz;
	

	public FromFileToDoubleArray() {
		matriz=new ArrayList<List<Double> >();
	}	
	
	private boolean isNumeric(String valor){
		try {
			Double.parseDouble(valor);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public void executeWithOutNormalize(File archivo) {
		logger.debug("procesando arch:" + archivo.getAbsolutePath());
		FileReader fr;
		try {
//			nombreArchivo="per-01.txt";
			//si pongo directamente un nombre, lo toma desde el raiz del proyecto
			fr = new FileReader(archivo);
			BufferedReader bf = new BufferedReader(fr);
		
			String sCadena=null;
			
			List<Double> listLinea =null;
			
			while ((sCadena = bf.readLine())!=null) {

				if ( isNumeric(sCadena.substring(0,1)) ){
				
					String[] valores=sCadena.split(" ");
	
					listLinea = new ArrayList<Double>();
	
					for (String valor:valores){
						
						if ( valor!=null && !valor.equals("") ){
							
							if ( !isNumeric(valor) ){
								//puede suceder si se me junta el menos de un numero siguiente con el actual, quedan 2 numeros
								String[] subValores=sCadena.split("-");
								
								//si es mayor a 1, entonces voy separando los valores
								if (subValores.length>1){

									String[] valoresStrings = getValores(valor);
									
									for (String doubleVal:valoresStrings){
										
										if ( doubleVal!=null && !doubleVal.equals("") && isNumeric(doubleVal) ){
											Double val=Double.parseDouble(doubleVal);
											listLinea.add(val);
											
											//obtener maximos y minimos
											if (val>maximo)
												maximo=val;
											if (val<minimo)
												minimo=val;
											
									//		System.out.println("Original: "+val );
																			
										}

									}
								}
							}
							else{
							
								Double val=Double.parseDouble(valor);
								listLinea.add(val);
								
								//obtener maximos y minimos
								if (val>maximo)
									maximo=val;
								if (val<minimo)
									minimo=val;
								
						//		System.out.println("Original: "+val  );
						
								}
							}
					}
					matriz.add(listLinea);
				}
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
			
		 logger.debug("fin proceso.");
	}

	
	/**
	 * Me llega varios numeros unidos por menos, y los tengo que separar
	 * ejemplo "3.253-2.365 -> 3.253 -2.365"
	 * @param valor
	 * @return
	 */
	private static String[] getValores(String cadena) {
		
		String resultado="";
		
		String[] valores = cadena.split("-");
		
		if (!valores[0].equals("")){
			resultado+=valores[0]+";";
		}
		
		for (int i = 1; i < valores.length; i++) {
			resultado+="-"+valores[i]+";";
		}

		return resultado.split(";");
	}

	private Double normaliza(Double valor){
		valor+=deltaNorm;
		if (valor<minNorm)
			valor=minNorm;
		if (valor>maxNorm)
			valor=maxNorm;

		return valor/maxNorm;
		
	}
	
	/**
	 * Le paso el maximo y minimo y me setea el rango
	 * @param max
	 * @param min
	 */
	public static void setMaxMinNormalizedValues(Double max,Double min){
		
		deltaNorm=-min;
		maxNorm=deltaNorm+max;
		minNorm=new Double(0.0);
		

	}
	
	public void mostrarValores() {
		for (List<Double> linea:matriz){
		
			for (Double valor:linea){
				System.out.print(valor+"  ");
			}
			System.out.println("nueava linea");
		}
		
	}


	public List<List<Double>> getMatriz() {
		return matriz;
	}


	public void setMatriz(List<List<Double>> matriz) {
		this.matriz = matriz;
	}
	

	/**
	 * Toma la matriz y me devuelve una lista con los valores
	 * que estan en la columna que paso por parametro
	 *
	 * @return devuelve una lista de valores reppresentando cada valor a una fila de la matriz
	 */
	public List<Double> getValuesByColumn(int columnNumber){
		List<Double> lista= new ArrayList<Double>();

		for (List<Double> linea:matriz){
			
			lista.add(linea.get(columnNumber));
		
		}

		return lista;
		
	}
	
	/**
	 * Toma la matriz y me devuelve una lista con los valores
	 * que estan en la columna que paso por parametro normalizados
	 *
	 * @return devuelve una lista de valores reppresentando cada valor a una fila de la matriz
	 */
	public List<Double> getValuesByColumnAndNormalice(int columnNumber){
		
		List<Double> lista= new ArrayList<Double>();

		for (List<Double> linea:matriz){
			
			lista.add(normaliza(linea.get(columnNumber)));
		
		}

		return lista;
		
	}

	
}
